package pers.lipeng.design_pattern.structural_mode._6_combination_mode;

/**
 * 组合模式
 * 当有新的文件类型时，只需要新建一个类，继承AbstractFile，实现ls方法即可
 * 优点：组合模式可以清楚地定义分层次的复杂对象，表示对象的全部或部分层次，
 * 它让客户端忽略了层次的差异，方便对整个层次结构进行控制。
 * 客户端可以一致地使用一个组合结构或其中单个对象，不必
 * 关心处理的是单个对象还是整个组合结构，简化了客户端代码。
 * 在组合模式中增加新的容器构件和叶子构件都很方便，无须对
 * 现有类库进行任何修改，符合“开闭原则”。
 * 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案，
 * 通过叶子对象和容器对象的递归组合，可以形成复杂的树形结构，
 * 但对树形结构的控制却非常简单。
 * 缺点：破坏了“单一职责原则”。
 *
 * 在增加新构件时很难对容器中的构件类型进行限制。
 * 有时候我们希望一个容器中只能有某些特定类型的对象，
 * 例如在某个文件夹中只能包含文本文件，使用组合模式时，
 * 不能依赖类型系统来施加这些约束，因为它们都来自于相同的抽象层，
 * 在这种情况下，必须通过在运行时进行类型检查来实现，这个实现过程较为复杂。
 */
class Demo {
    public static void main(String[] args) {
        AbstractFile musicFolder = new Folder("音乐文件夹");
        AbstractFile videoFolder = new Folder("视频文件夹");
        AbstractFile jpgFolder = new Folder("图片文件夹");

        AbstractFile music1 = new MusicFile("音乐文件1.mp3");
        AbstractFile music2 = new MusicFile("音乐文件2.mp3");
        AbstractFile music3 = new MusicFile("音乐文件3.mp3");

        AbstractFile video1 = new VideoFile("视频文件1.mv");
        AbstractFile video2 = new VideoFile("视频文件2.mv");
        AbstractFile video3 = new VideoFile("视频文件3.mv");

        AbstractFile image1 = new ImageFile("图片文件1.jpg");
        AbstractFile image2 = new ImageFile("图片文件2.jpg");
        AbstractFile image3 = new ImageFile("图片文件3.jpg");

        AbstractFile unkonwMusic = new MusicFile("未知音乐文件.mp3");

        musicFolder.add(music1);
        musicFolder.add(music2);
        musicFolder.add(music3);

        videoFolder.add(video1);
        videoFolder.add(video2);
        videoFolder.add(video3);

        jpgFolder.add(image1);
        jpgFolder.add(image2);
        jpgFolder.add(image3);

        AbstractFile top = new Folder("C盘");
        top.add(musicFolder);
        top.add(videoFolder);
        top.add(jpgFolder);
        top.add(unkonwMusic);

        top.ls("");
    }
}
